﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Windows.Input;

namespace AiMoWindows.MainActions.ScriptActions.SubActions
{
    class FormatScriptAction(ActionsController owner)
    {
        readonly ActionsController owner = owner;

        public delegate Key GetKeyEventHandler();

        //GetKeyEventHandler? getKeyFunc = null;

        //GetKeyEventHandler GetLastPressedKey => getKeyFunc ?? throw new InvalidOperationException("Document not initialized");
        //public void SetGetKeyAction(GetKeyEventHandler getKeyFunc)
        //{
        //    this.getKeyFunc = getKeyFunc;
        //}

        public async Task ReformatAfterChangeAsync()
        {
            // 当没有初始化，且没有在Format中，没有在BringBack时，才检测Update_Finished
            // 移除需要ReFormat
            if (!owner.HasState(SyncScriptState.NeedReFormatAfterChanged)) return;
            owner.RemoveState(SyncScriptState.NeedReFormatAfterChanged);

            // 添加正在ReFormat
            owner.AddState(SyncScriptState.InReFormat);
            //System.Diagnostics.Debug.WriteLine("ReformatAfterChange start");


            SyntaxNode root = await owner.GetCurrentSyntaxRoot();
            SyntaxToken currentToken = root.FindToken(formatPosition);
            SyntaxToken openBrace = FindOpenBraceToken(currentToken);


            if (currentToken.IsKind(SyntaxKind.UsingKeyword) && openBrace.IsKind(SyntaxKind.None))
            {
                // 可能修改了 #r "D:\Scripts\Aimo\AiMoRhino\Obfuscar\Out\lib\AiMoBridge.dll"
                // 目前修改的是最前面的using
                needSyncCode = true;
                PeformReformatAsync(new TextSpan(0, currentToken.FullSpan.End));
#if DEBUG
                owner.Printer.PrintDebug("Debug: 可能修改了 #r");
#endif
                return;
            }

            SyntaxTree tree = root.SyntaxTree!;
            SourceText text = tree.GetText();
            SyntaxToken closeBrace = FindCloseBraceToken(openBrace.IsKind(SyntaxKind.None) ? currentToken : openBrace);

            int start;
            int end;
            if (openBrace.IsKind(SyntaxKind.None))
            {
                // 找到了起点
                start = 0;
            }
            else
            {
                // 找到了{
                start = ExpandTokenToLineSpan(openBrace, tree, text).Start;
            }

            if (closeBrace.IsKind(SyntaxKind.None))
            {
                // 找到了终点
                end = text.Length;
            }
            else
            {
                end = ExpandTokenToLineSpan(closeBrace, tree, text).End;
            }

            TextSpan span = new TextSpan(start, end - start);
            await PeformReformatAsync(span);
        }

        async Task PeformReformatAsync(TextSpan span)
        {
            if (needSyncCode)
            {
                // 由于修改的代码中，包含外部using的更新，所以需要使用WithSync的Format
                needSyncCode = false;
                await owner.SyncAction.SyncScriptsWithFormat();
            }
            else
            {
                Document document = owner.CurrentDocument;
                owner.ScriptsHost.UpdateDocument(await FormatDocumentAsync(document, span));
            }
#if DEBUG
            owner.Printer.PrintDebug($"Debug: Perform Format at span{span}");
#endif
            //移除InReFormat
            owner.RemoveState(SyncScriptState.InReFormat);
            //System.Diagnostics.Debug.WriteLine("ReformatAfterChange end");
        }

        int formatPosition = 0;
        bool needSyncCode = false;
        long preTimeStampOfTextEntered = 0;
        public void IfNeedReFormatWhenChanged(ICSharpCode.AvalonEdit.Document.DocumentChangeEventArgs e)
        {
            if (owner.SyncState != SyncScriptState.None) return;

            long timeStamp = DateTime.Now.Ticks;
            if (e.InsertionLength > 0)
            {
                if (e.InsertedText.Text.Contains(';') || e.InsertedText.Text.Contains('}'))
                {
                    if (timeStamp - preTimeStampOfTextEntered > 500 * TimeSpan.TicksPerMillisecond)
                    {
                        owner.AddState(SyncScriptState.NeedReFormatAfterChanged);
                        formatPosition = e.Offset;
                    }
                    preTimeStampOfTextEntered = timeStamp;
                }
            }
            else if (e.RemovalLength > 0)
            {
                if (e.RemovedText.Text.Contains("#r "))
                {
                    needSyncCode = true;
                    if (timeStamp - preTimeStampOfTextEntered > 500 * TimeSpan.TicksPerMillisecond)
                    {
                        owner.AddState(SyncScriptState.NeedReFormatAfterChanged);
                        formatPosition = e.Offset;
                    }
                    preTimeStampOfTextEntered = timeStamp;
                }
            }
#warning 在这里修改 回车自动补全，括号自动补全等等
            //System.Diagnostics.Debug.WriteLine("IfNeedReFormat() end");
        }
        /// <summary>
        /// 向后查找}，并跳过中间的{}
        /// </summary>
        SyntaxToken FindCloseBraceToken(SyntaxToken token)
        {
            int openBraceCount = 0;
            do
            {
                token = token.GetNextToken();
                if (token.IsKind(SyntaxKind.OpenBraceToken))
                {
                    openBraceCount++;
                }
                if (token.IsKind(SyntaxKind.CloseBraceToken))
                {
                    if (openBraceCount <= 0) break;
                    openBraceCount--;
                }
            }
            while (!token.IsKind(SyntaxKind.None));
            return token;
        }
        /// <summary>
        /// 向前查找{，并跳过中间的{}
        /// </summary>
        SyntaxToken FindOpenBraceToken(SyntaxToken token)
        {
            int closeBraceCount = 0;
            do
            {
                token = token.GetPreviousToken();
                if (token.IsKind(SyntaxKind.CloseBraceToken))
                {
                    closeBraceCount++;
                }
                if (token.IsKind(SyntaxKind.OpenBraceToken))
                {
                    if (closeBraceCount <= 0) break;
                    closeBraceCount--;
                }
            }
            while (!token.IsKind(SyntaxKind.None));
            return token;
        }
        TextSpan ExpandTokenToLineSpan(SyntaxToken token, SyntaxTree tree, SourceText text)
        {
            LinePosition linePos = tree.GetLineSpan(token.Span).EndLinePosition;
            return text.Lines[linePos.Line].Span;
        }
        public async Task<Document> FormatDocumentAsync(Document document)
        {
            return await Microsoft.CodeAnalysis.Formatting.Formatter.FormatAsync(document).ConfigureAwait(false);
        }
        public async Task<Document> FormatDocumentAsync(Document document, TextSpan formatSpan)
        {
            return await Microsoft.CodeAnalysis.Formatting.Formatter.FormatAsync(document, formatSpan).ConfigureAwait(false);
        }
    }
}
